import com.intellij.database.model.DasTable
import com.intellij.database.model.ObjectKind
import com.intellij.database.util.Case
import com.intellij.database.util.DasUtil

/*
 * Available context bindings:
 *   SELECTION   Iterable<DasObject>
 *   PROJECT     project
 *   FILES       files helper
 */

packageName = ""
typeMapping = [
        (~/(?i)tinyint|smallint|mediumint/)      : "Integer",
        (~/(?i)int/)                             : "Long",
        (~/(?i)bool|bit/)                        : "Boolean",
        (~/(?i)float|double|decimal|real/)       : "Double",
        (~/(?i)datetime|timestamp|date|time/)    : "Date",
        (~/(?i)blob|binary|bfile|clob|raw|image/): "InputStream",
        (~/(?i)/)                                : "String"
]

FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->
  SELECTION.filter { it instanceof DasTable && it.getKind() == ObjectKind.TABLE }.each { generate(it, dir) }
}

def generate(table, dir) {
  def className = javaName(table.getName(), true)+"DO"
  def fields = calcFields(table)
  packageName = getPackageName(dir)
  def fos=new FileOutputStream(new File(dir, className + ".java"))
  def osw=new OutputStreamWriter(fos, "UTF-8")
  def  bw = new BufferedWriter(osw)
  generate(bw, className, fields)
  bw.close();
  osw.close();
  fos.close();
//  new File(dir, className + ".java").withPrintWriter { out -> out.write((new String(generate(out, className, fields).getBytes("UTF-8"))))  }
}


/**
 * 获取包名称
 * @param dir 实体类所在目录
 * @return
 */
def getPackageName(dir) {
  return dir.toString().replaceAll("\\\\", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "") + ";"
}

def generate(out, className, fields) {

  out.write("package $packageName \n")
  out.write("\n")

  Set types = new HashSet()

  fields.each() {
    types.add(it.type)
  }

  if (types.contains("Date")) {
    out.write("import java.util.Date;\n")
  }

  if (types.contains("InputStream")) {
    out.write("import java.io.InputStream;\n")
  }
  out.write("import lombok.ToString;\n")
  out.write("import lombok.Data;\n")
  out.write("\n")
  out.write("@Data\n")
  out.write("@ToString(callSuper = true)\n")
  out.write("public class $className extends BaseDO {\n")
  out.write("\n")
  fields.each() {
    if ("id".equals(it.name) || it.name == "gmtCreated" || it.name == "gmtModified" || it.name == "romaEnvIndicator" || it.name =="status"){
      return;
    }
    if (it.annos != "") out.write("  ${it.annos}\n")
    // 输出注释
    if (isNotEmpty(it.commoent)) {
      out.write("\t/**\n")
      out.write("\t * ${it.commoent}\n")
      out.write("\t */\n")
    }

    // 输出成员变量
    out.write("\tprivate ${it.type} ${it.name};\n")
  }
  out.write("\n")
  out.write("}\n")
  return out.toString();
}

def calcFields(table) {
  DasUtil.getColumns(table).reduce([]) { fields, col ->
    def spec = Case.LOWER.apply(col.getDataType().getSpecification())
    def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.value
    fields += [[
                       colName : col.getName(),
                       name    : javaName(col.getName(), false),
                       type    : typeStr,
                       commoent: col.getComment(),
                       annos   : ""]]
  }
}

def javaName(str, capitalize) {
  def s = str.split(/(?<=[^\p{IsLetter}])/).collect { Case.LOWER.apply(it).capitalize() }
          .join("").replaceAll(/\_/, "")
  capitalize || s.length() == 1? s : Case.LOWER.apply(s[0]) + s[1..-1]
}

def isNotEmpty(content) {
  return content != null && content.toString().trim().length() > 0
}